
#include "stdio.h"
#include "stdlib.h"
#include "gd32f1x0.h"
#include "systick.h"
#include "gd25q64.h"


//extern Controller_struct Controller;

void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte);
unsigned char ucgd25q64ReadStatusRegister(uint8_t GD25Q64_ReadStatusRegisterx);

void vgd25q64SPIInit(void){
	rcu_periph_clock_enable(gd25q64RCU_SPIx);
	rcu_periph_clock_enable(gd25q64RCU_GPIOx);
	
	gpio_af_set(gd25q64GPIOx, GPIO_AF_0, gd25q64GPIO_PIN_x);
	gpio_mode_set(gd25q64GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, gd25q64GPIO_PIN_x);
	gpio_output_options_set(gd25q64GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gd25q64GPIO_PIN_x);
	
	gpio_mode_set(gd25q64GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, gd25q64SPI_CS_PIN_x);
	gpio_output_options_set(gd25q64GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gd25q64SPI_CS_PIN_x);
	gpio_bit_write(gd25q64GPIOx,gd25q64SPI_CS_PIN_x,SET);
	
	spi_parameter_struct  spi_init_struct;
	spi_i2s_deinit(SPI0);

	spi_struct_para_init(&spi_init_struct);
	
	spi_init_struct.device_mode          = SPI_MASTER;
	spi_init_struct.prescale             = SPI_PSC_8;
	spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
	spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
	spi_init_struct.endian               = SPI_ENDIAN_MSB;
	spi_init_struct.nss                  = SPI_NSS_SOFT;
	spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
	
	spi_init(SPI0, &spi_init_struct);
	
	spi_enable(SPI0);
}

uint8_t gd25q64Data[gd25q64DataLen]={0};

uint8_t spi_master_send_recv_byte(uint8_t spi_byte)
{
	uint8_t ByteRecv;
	while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE))
		;
	spi_i2s_data_transmit(SPI0,spi_byte);
	while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE))
		;
	ByteRecv=spi_i2s_data_receive(SPI0);
	return ByteRecv;
}

void spi_master_recv_some_bytes( uint8_t *pbdata, uint16_t recv_length)
{
  uint8_t * temp_data = pbdata;

	while (recv_length--)
	{
		*temp_data = spi_master_send_recv_byte(0xFF);	//发送 0xff 为从设备提供时钟
		temp_data++;
	}
}

void vgd25q64WriteEnable(void){
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_WriteEnable);
	GD25Q64_CS_HIGH();
}

void Flash_EraseSector(uint32_t _ulEraseAddr)
{
//	uint8_t rsr2 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister2);
//	uint8_t rsr3 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister3);
//	uint8_t rsr1 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1);
	vgd25q64WriteEnable();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_SectorErase);
	spi_master_send_recv_byte((uint8_t)(_ulEraseAddr>>16));
	spi_master_send_recv_byte((uint8_t)(_ulEraseAddr>>8));
	spi_master_send_recv_byte((uint8_t)(_ulEraseAddr));
	GD25Q64_CS_HIGH();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
}

void Flash_EraseChip(void)
{
	vgd25q64WriteEnable();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_ChipErase);
	GD25Q64_CS_HIGH();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
}

unsigned int uigd25q64ReadIdentification(void)
{
	uint32_t Identification = 0;
	uint8_t recv_buff[3] = {0};
	
	GD25Q64_CS_LOW();

	spi_master_send_recv_byte(GD25Q64_ReadIdentification);	//9fh
	
	uint8_t recvLen = sizeof(recv_buff);

	for(uint8_t i = 0 ; i < recvLen;i++)
	{
		recv_buff[i] = spi_master_send_recv_byte(0xFF);	//发送 0xff 为从设备提供时钟
	}
	
	Identification = (recv_buff[0] <<16) | (recv_buff[1] <<8) | (recv_buff[2]);

	GD25Q64_CS_HIGH();
	
	return Identification;
}

unsigned short usgd25q64ReadID(void)
{
  	uint16_t ID = 0;
   	GD25Q64_CS_LOW();

		spi_master_send_recv_byte(GD25Q64_ManufacturerDeviceID);
		spi_master_send_recv_byte(0x00);
		spi_master_send_recv_byte(0x00);
		spi_master_send_recv_byte(0x00);

		ID |= spi_master_send_recv_byte(0xFF)<<8;
		ID |= spi_master_send_recv_byte(0xFF);
  
   	GD25Q64_CS_HIGH();
	
  	return ID;
}

unsigned char ucgd25q64ReadStatusRegister(uint8_t GD25Q64_ReadStatusRegisterx)
{
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_ReadStatusRegisterx);
	uint8_t StatusRegisterx=spi_master_send_recv_byte(0xFF);
	GD25Q64_CS_HIGH();
	return StatusRegisterx;
}

void vgd25q64WriteStatusRegister1(unsigned char _ucByte,uint8_t GD25Q64_ReadStatusRegisterx)
{
	vgd25q64WriteEnable();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_ReadStatusRegisterx);
	spi_master_send_recv_byte(_ucByte);
	GD25Q64_CS_HIGH();
}

bool vgd25q64WriteManyBytes(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte)
{
	uint32_t DataAdd = _ulWriteAddr;
	Flash_ReadSomeBytes(gd25q64Data,DataAdd,GD25Q64_PageSize);
	for(uint32_t i=0;i<_usNByte;i++)
	{
		if(gd25q64Data[i]!=0xFF){
			return FALSE;
		}else{
			gd25q64Data[i]=ucpBuffer[i];
		}
	}
	vgd25q64WriteEnable();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
	GD25Q64_CS_LOW();
	spi_master_send_recv_byte(GD25Q64_PageProgram);
	spi_master_send_recv_byte(DataAdd>>16);
	spi_master_send_recv_byte(DataAdd>>8);
	spi_master_send_recv_byte(DataAdd>>0);
	for(uint32_t i =0;i<_usNByte;i++)
	{
		spi_master_send_recv_byte(gd25q64Data[i]);
	}
	
	GD25Q64_CS_HIGH();
	while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01)==0x01)
		;
	return TRUE;
}

void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
	uint8_t * temp_data = ucpBuffer;
	
	GD25Q64_CS_LOW();
	
	spi_master_send_recv_byte(GD25Q64_ReadData);
	spi_master_send_recv_byte((uint8_t)(_ulReadAddr >> 16));
	spi_master_send_recv_byte((uint8_t)(_ulReadAddr >> 8));
	spi_master_send_recv_byte((uint8_t)(_ulReadAddr >> 0));

	while (_usNByte--)
	{
		*temp_data = spi_master_send_recv_byte(0xFF);	//发送 0xff 为从设备提供时钟
		temp_data++;
	}
	
	GD25Q64_CS_HIGH();
}
void vgd25q64ReadData(uint8_t *buffer, uint32_t add, uint16_t len)
{
	Flash_ReadSomeBytes(buffer,add,len);
}

void vgd25q64WriteData(unsigned  char data[],unsigned int add,unsigned short length)
{
	 vgd25q64WriteManyBytes(data,add,length);
}


//Flash_EraseSector(1);//按地址的 0 1 都是片0
//vgd25q64ReadData(ceshi,Posflechazo,512);
//vgd25q64WriteData((unsigned  char *)ControllerInfoInitData,0,(unsigned short)InfoLength);
//vgd25q64ReadData(ceshi,Posflechazo,512);	
//Flash_EraseSector(0);
//Flash_EraseChip();
